package gupao.concurrency.threads;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

@Slf4j
public class WaitNotifyDemo2 {
    volatile static boolean stop = false;
    static int productNumber = 0;//产品编号记录
    private static Product product;
    static Object obj = new Object();

    public static void main(String[] args) throws InterruptedException {
        WaitNotifyDemo2 demo = new WaitNotifyDemo2();
        new Thread(new Producer()).start();
        new Thread(new Consumer()).start();
        wait2Complete();
    }

    private static void wait2Complete() throws InterruptedException {
        TimeUnit.SECONDS.sleep(10);
        stop = true;
    }

    @AllArgsConstructor
    static class Product{
        int number;
    }
    static class Producer implements Runnable{
        @Override
        public void run() {
            while(!stop) {
                synchronized (obj){
                    while(product != null){
                        log.warn("等待产品被消费掉先..");
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            //ignore
                        }
                    }
                    productNumber++;
                    log.info("产品({})开始生产", productNumber);
                    Utils.sleepIgnoreExp(1000);
                    product = new Product(productNumber);
                    log.info("产品({})已经生产好，请自取", productNumber);
                    obj.notifyAll();
                }
            }
        }
    }
    static class Consumer implements Runnable{
        @Override
        public void run() {
            while(!stop){
                synchronized (obj){
                    while(product == null){
                        log.warn("没有产品可以消费, 等待..");
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            //ignore
                        }
                    }
                    log.info("产品({})已拿到，开始享用.", product.number);
                    Utils.sleepIgnoreExp(1000);
                    log.info("产品({})已消费.", product.number);
                    product = null;
                    obj.notifyAll();
                }
            }
        }
    }
}
